from __future__ import annotations
from math import floor

from base.common_enum import Camp, Rarity, get_enum
from base.ship_enum import ArmorType, ShipType, SpecialType, ShipAttr
from .state import ShipState


class ShipGrowthAttrs:
    def __init__(self, hp: int, rld: int, fp: int, trp: int, eva: int, aa: int, avi: int, acc: int, asw: int):
        """
        舰船属性成长值
        :param hp: 耐久
        :param rld: 装填
        :param fp: 炮击
        :param trp: 雷击
        :param eva: 激动
        :param aa: 防空
        :param avi: 航空
        :param acc: 命中
        :param asw: 反潜
        """
        self.hp = hp
        self.rld = rld
        self.fp = fp
        self.trp = trp
        self.eva = eva
        self.aa = aa
        self.avi = avi
        self.acc = acc
        self.asw = asw


class ShipBaseAttrs(ShipGrowthAttrs):
    def __init__(self, hp: int, armor_type: ArmorType, rld: int, fp: int, trp: int, eva: int, aa: int, avi: int,
                 acc: int, asw: int, spd: int, lck: int, cost: int):
        """
        舰船属性基础值
        :param hp: 耐久
        :param armor_type: 装甲类型
        :param rld: 装填
        :param fp: 炮击
        :param trp: 雷击
        :param eva: 机动
        :param aa: 防空
        :param avi: 航空
        :param acc: 命中
        :param asw: 反潜
        :param spd: 航速
        :param lck: 幸运
        :param cost: 满破油耗
        """
        super().__init__(hp, rld, fp, trp, eva, aa, avi, acc, asw)
        self.armor_type = armor_type
        self.spd = spd
        self.lck = lck
        self.cost = cost


class ShipAttrs:
    def __init__(self, camp: Camp, name: str, ship_type: ShipType,
                 ship_rarity: Rarity, base_attrs: ShipBaseAttrs,
                 growth_attrs: ShipGrowthAttrs, state: ShipState,
                 special_type: SpecialType = SpecialType.NULL):
        """
        舰船属性模块, 存储舰船属性常量, 可以返回根据属性常量和状态计算出的属性结果(白值)
        :param camp: 阵营
        :param name: 舰名
        :param ship_type: 舰船类型
        :param ship_rarity: 稀有度
        :param base_attrs: 属性基础值
        :param growth_attrs: 属性成长值
        :param state: 舰船状态信息
        :param special_type: 特殊类型
        """
        self._camp = camp
        self._name = name
        self._special_type = special_type
        self._type = ship_type
        self._rarity: Rarity = ship_rarity
        self._base_attrs = base_attrs
        self._growth_attrs = growth_attrs
        self._state = state

    @property
    def _ship_type(self):
        """舰船类型"""
        if (self._state.retrofit.flag_allowed and self._state.retrofit.flag_enable
                and self._state.retrofit.ship_type_change is not None):
            return self._state.retrofit.ship_type_change
        return self._type

    @property
    def _ship_rarity(self) -> Rarity:
        """舰船稀有度"""
        if self._state.retrofit.flag_allowed and self._state.retrofit.flag_enable:
            return Rarity(get_enum(Rarity, self._rarity.value[0] + 1))
        return self._rarity

    @property
    def state(self):
        """舰船状态信息"""
        return self._state

    @property
    def _affinity(self):
        return self._state.affinity

    @property
    def _affinity_level(self):
        return self._state.affinity_level

    @property
    def _oath(self):
        return self._state.oath

    @property
    def _morale(self):
        return self._state.morale

    @property
    def _level(self):
        return self._state.level

    @property
    def _enhancement(self):
        return self._state.enhancement

    @property
    def _limit_break(self):
        return self._state.limit_break

    @property
    def _retrofit(self):
        return self._state.retrofit

    @property
    def _armor_type(self):
        if self._retrofit.flag_enable and self._retrofit.armor_type_change:
            return self._retrofit.armor_type_change
        return self._base_attrs.armor_type

    def get_attr(self, attr: ShipAttr):
        match attr:
            case ShipAttr.COST:
                if self._ship_type in [ShipType.SS, ShipType.SSV]:
                    return floor((self._base_attrs.cost + self._limit_break.breakthrough_grade - 2)
                                 * (0.5 + min(self._level, 99) * 0.005))
                else:
                    return floor((self._base_attrs.cost - (3 - self._limit_break.breakthrough_grade) * 2)
                                 * (0.5 + min(self._level, 99) * 0.005) + 1)
            case ShipAttr.HP | ShipAttr.RLD | ShipAttr.FP | ShipAttr.TRP | ShipAttr.EVA | ShipAttr.AA \
                 | ShipAttr.AVI | ShipAttr.ACC | ShipAttr.ASW | ShipAttr.SPD | ShipAttr.LCK:
                base_value = getattr(self._base_attrs, attr.value)
                try:
                    growth_value = getattr(self._growth_attrs, attr.value) * (self._level - 1) / 1000
                except AttributeError:
                    growth_value = 0
                try:
                    limit_break_value = getattr(self._limit_break.attrs_inc, f'{attr.value}_inc')
                except AttributeError:
                    limit_break_value = 0
                try:
                    enhancement_value = getattr(self._enhancement, f'{attr.value}')
                except AttributeError:
                    enhancement_value = 0
                try:
                    retrofit_value = 0 if self._retrofit.get_inc_by_attr(
                        attr.value) is None else self._retrofit.get_inc_by_attr(
                        attr.value) if self._retrofit.flag_enable else 0
                except AttributeError:
                    retrofit_value = 0
                if attr in [ShipAttr.SPD, ShipAttr.LCK]:
                    return floor(base_value + growth_value + limit_break_value + enhancement_value + retrofit_value)
                return floor((base_value + growth_value + limit_break_value + enhancement_value)
                             * self._affinity_level.value + retrofit_value)
            case ShipAttr.ENHANCEMENT | ShipAttr.RETROFIT:
                return getattr(getattr(self, f'_{attr.value}'), 'flag_enable')
            case ShipAttr.LIMIT_BREAK:
                return self._limit_break.breakthrough_grade
            case ShipAttr.CAMP | ShipAttr.RARITY | ShipAttr.ARMOR:
                return getattr(getattr(self, f'_{attr.value}'), 'value')[1]
            case ShipAttr.TYPE | ShipAttr.SPECIAL_TYPE:
                return getattr(getattr(self, f'_{attr.value}'), 'value')
            case _:
                try:
                    return getattr(self, f'_{attr.value}')
                except AttributeError as e:
                    pass
